package yxy.game.sdk.huawei;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.codec.binary.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import yxy.apple.http.server.business.BusinessType;
import yxy.apple.logger.Logger;
import yxy.cherry.game.base.bean.SDKParm;
import yxy.cherry.game.base.bean.SdkParmEnum;
import yxy.game.bean.LoginOtherParm;
import yxy.game.login.Error;
import yxy.game.login.LoginModule;
import yxy.game.util.HttpUtil;

@BusinessType(code = "LOGIN")
public class Login extends Sdk_huawei {

	private static final Logger logger = Logger.create(Login.class);

	@Override
	public JSONObject handle(JSONObject request) throws Exception {
		System.out.println(request.toString());
		JSONObject result = new JSONObject();
		logger.info("sdk_huawei:" + request);
		
//		验证公钥：MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlaw1QtQ0vZhp06n83uxCPoWKB9ZhKOZC1GLy1G6NrDr+UwOPzNQBewGPJJbvkFMbRPk4jKyA7j3BQfHh/WBcN7od+FR5wAk0cbgzhpHrS06vVFKcM2Eg9ZFuX74f/tzeYULBpbdKXsmezbpRsm3AGO5O/uKQQjSOcTJvkn0UcSzHmLVs8P1WDRgXvTl/qhKYO5KiQAftKd+IAej65/nN5/jKOozC5aDt5rTVatKdB3AMkxKDU+pOuIYci04sVF57D9h5vTg9qVmn4pkKUZXaTi8enLhC9qO158AtKFM2W1PEdyGgA2NXvSUEvYq/nn7/qbJujoTi6R/xyhefLsSAQQIDAQAB
//		项目ID	736430079244723300
//		Client ID：	508397489141854848
//		Client 密钥： 19CE0FA0590541551765BDE18E820F57A5B4158AFA36D96A1B83AD3F82EB80EC
//		APP ID：	103401247
//		API KEY: CgB6e3x9Z3jJqCajSL1udx3QNFkUuq8FcJW+rfRV30eCEHx/53Hc8bdGlTVC5Oy9P8Pm5YmzelsUbRmQmz2rmmtT
//		APP SECRET：	58339a014869396c918cf06f8be6c03ae5fe54a8e7111a92a6cecef2547fac16
//		支付公钥	MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAiAOD2dCdYKlXfrvjgTn3NzICyCRfZINmvoIF6HTYRlCeU5wYRJz8J9mdQIdZw5ps42R6fNk0NRHsxU8kMvW38BoreGypl47fkL6HlvvQXhd1gZ5mnjyxhj/OhmTstr/qJQY8+bqcyBfJolSDsszNNqsftzFCYD3WeR34HNewN1HYwq7L8sf8WUiJZGamvjvTacFlctfY49OqI+Eaf6NkEcHRTYHDfbscHF3u2lY8GegMi0XYOzoghlTlqI5guzgMHmM1BH0XREz6tEWePjx8VuT5XCWRtD7gd2i3viuuu8Juk9jQpsL7hiMGE1wIsPH2M5xPPnI7K5r53DOzdwYmu1/aUv+Ex0AKXM7h5QgnDUvnmmYDb4Ki5+yp9x4X2hod8+0+zFF6J5RHMJyCiLsJvQiwnGvyUJ/l12ao0mt3Dm+v3x2f1UlPbUxxbvTnR1NAZ9e0CaB74dvzXPdCcirXEtnM1CCuoGK2w/1u7KAEZTQkpSQuvUdFge7XfT/gFxhnAgMBAAE=

//		参数名称		必选(M)/可选(O)	类型		是否参与签名	参数说明
//		method		M				string	是			固定传入“external.hms.gs.checkPlayerSign”。
//		appId		M				string	是			游戏的应用ID，在创建应用后由华为开发者联盟为应用分配的唯一标识。应用ID的查询方法请参见查询应用信息。
//		cpId		M				string	是			商户ID，即华为开发者联盟给开发者分配的“支付ID”。支付ID的查询方法请参见查询支付服务信息。
//		ts			M				string	是			时间戳，取自当前玩家的Player对象。
//		playerId	M				string	是			玩家ID，取自当前玩家的Player对象。
//		playerLevel	M				string	是			玩家等级，取自当前玩家Player.getLevel方法，必须转化为string类型。
//		playerSSign	M				string	是			登录签名，取自当前玩家的Player对象。
//		cpSign		M				string	否			用于华为游戏服务器对请求参数验签的签名字符串。为防止请求被篡改，
//														应用需要根据登录验签接口签名字符串的生成方法中的方法生成签名字符串，
//														华为服务器在收到请求后会对签名字符串进行验签，验签成功后才会进行后续处理，否则将返回失败错误码。

		JSONObject datajson = request.getJSONObject("datajson");
		String ts = datajson.getString("signTs");
		String playerId = datajson.getString("userId");
		String playerLevel = datajson.getString("userLevel");
		String playerSSign = datajson.getString("playerSign");
		String subchannel = datajson.getString("subchannel");

		String method = "external.hms.gs.checkPlayerSign";
//		String appId = "103401247";
//		String cpId = "890086000102339385";
		String appId = SDKParm.getSdkparmvalue(SdkParmEnum.huawei_appid);
		String cpId = SDKParm.getSdkparmvalue(SdkParmEnum.huawei_cpid);

		// 签名
		HashMap<String, String> signmap = new HashMap<String, String>();
//		signmap.put("method", "external.hms.gs.checkPlayerSign");
		signmap.put("method", method);
		signmap.put("appId", appId);
		signmap.put("cpId", cpId);
		signmap.put("ts", ts);
		signmap.put("playerId", playerId);
		signmap.put("playerLevel", playerLevel);
		signmap.put("playerSSign", playerSSign);

		String cpauthkey = SDKParm.getSdkparmvalue(SdkParmEnum.huawei_paypublickey);
//				"MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCrgr6NLCdxP5uF8QhRfYIWDwR50LpE064t69Q0kBhphH3Hr0lyH9W7d+vZKpMfQ2jq/+NegqwjC/lcHiJ0Esl2NiZCvthP/oCKjkQ2REQbGPaMSEnt7AGcnpu4JJ1bTYvFoZzaWB8JIagXSPLIInkj3WjsY0ovZiyppgD5ikQUR5cHWybq6OG19KKxGQbE6KvGIlAHSvqU9/HKD6+4sp7rOLV6Ku17TiksOO5lzPJEw8oOjwUIQiad12mQIEUYODu4DkHpvuQiIk6LT5JWWUl0CKKBfRPPdeNZpZc7eI55+PsMIuSb8WdJvKHVVT3Yg3fAQUMnw6hcjf1BkAXqWZs7AgMBAAECggEBAKXdp5K3pN1s+mcqlzTYADp9A4MbTUjKvqRCcdLzl+hT7aBz8L+h8f1/GGPJPMb7VjgOiEEadobeSaXAruk6UgM0kwPxtRiHtKBKvcUNeCAMoENCldy2ZUimS0pmfpeSAx56EUtH9ZvLJNh//+t1C1qYAaS60T/NvFvE4yRxhy1kA/yl6XAYJlWoSv520QMTTnVKHQteGjel1yPy+zpud1pJJwGZSChThdCiNqT3ZlHTNltxGFTNE6u9GjD13w04sxiTmcLWPrHNx2b15FXruyjIAMWjpAK4CZOV0kAHtUIYyRG2jyXBADIQOo1J9UkB1MdQ+BrZRydvsHvs7RSDY8ECgYEA9sorfJcY2YGO7v7qgx5/Gt5MvbJvRaTUwNlntUsF2p/FzqMKJeTx+nbPec0PAQXlD+FM8YhjP6snuUYYEkeLbPo+DkSyKNY+Y8J5wmjPLi2Cu4ff3ZalkMA/zizmNl5nipe1kaM17Sswrze6Cls8LidY9jkfAepvWwt+Vg7+LjMCgYEAselbx8XKWe7lwX+rSwvPM1MceR8Pe2XJ+tMdDTqY5zjZw9myHdcqSFDrFQScWxkfSbd6tKcwotQt/hMROt1gA65jmrak51bDAF3bkRiQYxbQ9YqmRNmm1N7nxfarExiOBHh//2BkVkm3FUgKDocGQBOTqKttLUC73oJGD/MzxtkCgYEA0sR4/VACDgjDLMQTPuY1wZmnSr9wnrcWaJmEI+Yt2rhndIHz8cclDjaYHTsPHF2Pcs+FKibENKUVKPt/JWVq4yiZBRCQY6YN5J8749glURfXNhfmDlZRkl1OYOQhvL9FiKzmibotHR+s1YgvYBbpP7WlGaxRGg7BCa24OQFW/dcCgYBXnbfga0za+2bU413lSHyTJyQHlj9WoutUhjFxeWEhxgKgjA5G2dbt5EPRhwLFblrVP/HDE+9E0T+RN6ytk6YcSf6ti7MsZrMD9DUUgMditTLVKaH2mEWr4da8zFy1u8r88qb+imb/g7ARX/fr7Z0rYzi9wSa0OYQL8ZY1dq0SCQKBgQC7OzDXnMzny7WoM3Gl0d6D+bVeXPgWeWFMsnjb5AY7bZOYO1nlEj/mDwvF/vGH5QvaVgtrD47ET5bIaQsTSreWyzFsxsfUpb0HszVGRLO5uMrC+9/6Kw3urcCfWTd1lg7RkTDs4xkk9LYE2PJHDHEjiLQmXxELDmdEt27dc7v+pg==";
//		String cpauthkey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlaw1QtQ0vZhp06n83uxCPoWKB9ZhKOZC1GLy1G6NrDr+UwOPzNQBewGPJJbvkFMbRPk4jKyA7j3BQfHh/WBcN7od+FR5wAk0cbgzhpHrS06vVFKcM2Eg9ZFuX74f/tzeYULBpbdKXsmezbpRsm3AGO5O/uKQQjSOcTJvkn0UcSzHmLVs8P1WDRgXvTl/qhKYO5KiQAftKd+IAej65/nN5/jKOozC5aDt5rTVatKdB3AMkxKDU+pOuIYci04sVF57D9h5vTg9qVmn4pkKUZXaTi8enLhC9qO158AtKFM2W1PEdyGgA2NXvSUEvYq/nn7/qbJujoTi6R/xyhefLsSAQQIDAQAB";	
		String cpSign = generateCPSign(signmap, cpauthkey);
		logger.info("sdk_huawei:" + cpSign);

		JSONObject postjson = new JSONObject();
		postjson.put("method", method);
		postjson.put("appId", appId);
		postjson.put("cpId", cpId);
		postjson.put("ts", ts);
		postjson.put("playerId", playerId);
		postjson.put("playerLevel", playerLevel);
		postjson.put("playerSSign", playerSSign);
		postjson.put("cpSign", cpSign);

		logger.info("sdk_huawei postjson:" + postjson);

		String urlbc = format(postjson);
		StringBuffer urlall = new StringBuffer();
		urlall.append(checklogin).append("/?").append(urlbc);

		JSONObject retjson = HttpUtil.response(urlall.toString(), 30000, null);	

		logger.info("sdk_huawei retjson:" + retjson);
		if (retjson == null || retjson.equals("")) {
			logger.info("sdk_huawei ret is null");
			return result(result, Error.Err_渠道代码错误);
		}

		int rtnCode = retjson.getIntValue("rtnCode");
		if (rtnCode != success) {
			logger.info("sdk_huawei rtnCode is not " + success);
			return result(result, Error.Err_渠道代码错误);
		}

		String username = playerId;
		String password = playerId;
		String channel = name();

		String ip = request.getString("ip");
		int clusterId = request.getInteger("clusterId");

		LoginOtherParm loginOtherParm = new LoginOtherParm();
		loginOtherParm.setClusterId(clusterId);

		return new LoginModule().login(username, password, channel, subchannel, ip, loginOtherParm);
	}

	public JSONObject result(JSONObject result, Error errcode) {
		result.put("result", errcode.number());
		return result;
	}

	private static String generateCPSign(Map<String, String> requestParams, final String cpAuthKey) {
		// 对消息体中查询字符串按字典序排序并且进行URLCode编码
		String baseStr = format(requestParams);
		// 用CP侧签名私钥对上述编码后的请求字符串进行签名
		String cpSign = sign(baseStr.getBytes(Charset.forName("UTF-8")), cpAuthKey);
		return cpSign;
	}

	private static String sign(byte[] data, String privateKey) {
		try {
			byte[] e = Base64.decodeBase64(privateKey);
			PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(e);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
			Signature signature = Signature.getInstance("SHA256WithRSA");
			signature.initSign(privateK);
			signature.update(data);
			String signs = Base64.encodeBase64String(signature.sign());
			return signs;
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
	}

	private static String format(Map<String, String> params) {
		StringBuffer base = new StringBuffer();
		Map<String, String> tempMap = new TreeMap<String, String>(params);
		// 获取计算nsp_key的基础串
		try {
			for (Map.Entry<String, String> entry : tempMap.entrySet()) {
				String k = entry.getKey();
				String v = entry.getValue();
				base.append(k).append("=").append(URLEncoder.encode(v, "UTF-8")).append("&");
			}
		} catch (UnsupportedEncodingException e) {
			System.out.println("Encode parameters failed.");
			e.printStackTrace();
		}
		String body = base.toString().substring(0, base.toString().length() - 1);
		// 空格和星号转义
		body = body.replaceAll("\\+", "%20").replaceAll("\\*", "%2A");
		return body;
	}

	/**
	 * 生成待签名字符串
	 * 
	 * @param params
	 * @return
	 */
	private static String format(JSONObject json) {
		StringBuffer base = new StringBuffer();

		List<String> keys = new ArrayList<String>(json.keySet());
		Collections.sort(keys);

		try {
			for (int i = 0; i < keys.size(); i++) {
				String k = keys.get(i);
				String v = json.getString(k);
				base.append(k).append("=").append(URLEncoder.encode(v, "UTF-8")).append("&");
			}
		} catch (UnsupportedEncodingException e) {
			System.out.println("Encode parameters failed.");
			e.printStackTrace();
		}
		
		String body = base.toString().substring(0, base.toString().length() - 1);
		// 空格和星号转义
		body = body.replaceAll("\\+", "%20").replaceAll("\\*", "%2A");
		return body;
	}

//	public String http_build_query(JSONObject json) {
//		String reString = null;
//		// 遍历数组形成akey=avalue&bkey=bvalue&ckey=cvalue形式的的字符串
//
//		List<String> keys = new ArrayList<String>(json.keySet());
//		Collections.sort(keys);
//
//		for (int i = 0; i < keys.size(); i++) {
//			String key = keys.get(i);
//			String value = json.getString(key);
//			StringBuilder sBuilder = new StringBuilder();
//			sBuilder.append(key).append("=").append(value).append("&");
////			reString += key+"="+value+"&";
//			if (reString == null) {
//				reString = sBuilder.toString();
//			} else {
//				reString = reString + sBuilder.toString();
//			}
//		}
//		reString = reString.substring(0, reString.length() - 1);
//		// 将得到的字符串进行处理得到目标格式的字符串
////		try {
////			reString = java.net.URLEncoder.encode(reString, "utf-8");
////		} catch (UnsupportedEncodingException e) {
////			e.printStackTrace();
////		}
////		reString = reString.replace("%3D", "=").replace("%26", "&");
//		System.out.println("====huawei restring:" + reString);
//		return reString;
//	}

	public static void main(String[] str) {
		String jsonstr = "{\"password\":\"1186143468501532\",\"business\":\"sdk_huawei\",\"ip\":\"/111.163.123.51:28912\",\"datajson\":\"{\\\"uid\\\":\\\"1186143468501532\\\",\\\"userId\\\":\\\"1186143468501532\\\",\\\"userKey\\\":\\\"159******82\\\",\\\"subchannel\\\":\\\"huawei\\\",\\\"userLevel\\\":1,\\\"playerSign\\\":\\\"Y+P+bN2BAdNrLX8DyEglb42wch0PTXIuA/4XpIlJwWU+0nOnq4SPoWAEE7oU+nHoHzCI/6PQCdfzcX4ZF4svDx7MgEqTo6o2lDYqj03wbzxG8yJ8ONc8oCZ0g8/vnZweD4g970UpjVUVf9vIB+xhRRpFEm100Yqz+k4H8DHSk8mzo4YayWOF3rRVhkrBS74/1394AVP+PTb0mHZ0NFNLUwgR5dDMezn/1gMIfjUoYycinXIFk1P7CpoG6QpXBW3VZFuS7XP11x14zPOFdbsrK/ZPZy672iGeuijJIogFvsgw0DafUX2go7pJqJ9N+zO6hYLj1UpMZzmwjv5jJPRqbQ==\\\",\\\"signTs\\\":\\\"1608533736630\\\"}\",\"username\":\"1186143468501532\"}";
		JSONObject json = JSON.parseObject(jsonstr);
		Login login = new Login();
		try {
			login.handle(json);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
